package com.net.xpay.common.service.impl;

import com.net.xpay.common.domain.User;
import com.net.xpay.common.domain.UserShard;
import com.net.xpay.common.domain.stat.UserRealTimeStat;
import com.net.xpay.common.helper.RedisHelper;
import com.net.xpay.common.manager.UserManager;
import com.net.xpay.common.manager.UserShardManager;
import com.net.xpay.common.manager.stat.UserRealTimeStatManager;
import com.net.xpay.common.model.search.UserSearchModel;
import com.net.xpay.core.constant.RedisKey;
import com.net.xpay.core.enums.SafePayOrderStatus;
import com.net.xpay.core.manager.ChargeRecordManager;
import com.net.xpay.core.manager.PayTransBatchManager;
import com.net.xpay.core.manager.PayTransManager;
import com.net.xpay.core.manager.safePay.SafePayBatchManager;
import com.net.xpay.core.manager.safePay.SafePayOrderManager;
import com.net.xpay.core.model.PartnerUserPayTransDayStatModel;
import com.net.xpay.core.model.PartnerUserSafePayTransDayStatModel;
import com.net.common.util.LocalDateUtil;
import com.net.xpay.common.service.UserRealTimeStatService;
import com.net.shard.ShardUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class UserRealTimeStatServiceImpl implements UserRealTimeStatService {

    @Autowired
    private UserManager userManager;

    @Autowired
    private UserShardManager userShardManager;

    @Autowired
    private ChargeRecordManager chargeRecordManager;

    @Autowired
    private PayTransBatchManager payTransBatchManager;

    @Autowired
    private PayTransManager payTransManager;

    @Autowired
    private SafePayOrderManager safePayOrderManager;

    @Autowired
    private SafePayBatchManager safePayBatchManager;

    @Autowired
    private UserRealTimeStatManager userRealTimeStatManager;

    @Autowired
    private RedisHelper redisHelper;

    @Override
    public void statUserRealTimeStat(LocalDateTime time) {
        UserSearchModel searchModel = new UserSearchModel();
        List<Long> userIds = userManager.listIds(searchModel);

        log.info("statUserRealTimeStat userIds={}", userIds);
        if (CollectionUtils.isEmpty(userIds)) {
            return;
        }
        for (Long userId : userIds) {
            try {
                doUserRealTimeStat(userId, time);
            } catch (Exception e) {
                log.error("statUserRealTimeStat error|userId={}", userId, e);
            }
        }
        redisHelper.set(RedisKey.USER_REAL_TIME_STAT_UPDATE_TIME, LocalDateUtil.getDateTimeAsString(time));
    }

    @Override
    public void doUserRealTimeStat(Long userId, LocalDateTime maxEndTime) {
        User user = userManager.getById(userId);
        //注册时间在统计时间之后的不统计
        if (user.getRegisterTime().isAfter(maxEndTime)) {
            return;
        }
        // 通过userID获取到userShard
        UserShard userShard = userShardManager.getById(userId);
        try {
            // 切库处理
            ShardUtil.setShardContext(userShard.getShardId());
            //初始化
            UserRealTimeStat stat = UserRealTimeStat.getInstance(userId,maxEndTime);
            stat.setPartnerId(user.getPartnerId());
            // 获取当天的起始时间和终止时间 终止时间保留在当前时间
            LocalDateTime minEndTime = LocalDateUtil.getDayStart(maxEndTime);

            //统计数据并入库
            saveUserRealTimeStat(stat,userId,minEndTime,maxEndTime);

        } finally {
            ShardUtil.cleanShardContext();
        }
    }

    private void saveUserRealTimeStat(UserRealTimeStat stat,Long userId,LocalDateTime minEndTime,LocalDateTime maxEndTime) {
        //统计查询
        //服务费充值金额
        long serviceChargeFee = chargeRecordManager.sumUserServiceChargeFeeByDay(userId,minEndTime, maxEndTime);
        //批量有密单笔超过500金额成功笔数
        long payTransSuccessSingleVeryCount = payTransManager.statUserSingleVeryCount(userId,minEndTime, maxEndTime);
        //批量有密单笔超过500金额失败笔数
        long payTransFailSingleVeryCount = payTransManager.statUserFailSingleVeryCount(userId,minEndTime, maxEndTime);
        //批量有密单笔超过10000金额成功笔数
        long payTransSuccessLargeCount = payTransManager.statUserLargeCount(userId,minEndTime, maxEndTime);
        //批量有密超过500万账户数
        long payTransVeryAlipayUserCount = payTransBatchManager.sumUserTotalVeryAlipayUserCount(userId,minEndTime, maxEndTime);
        //安全发单笔超过500金额成功笔数
        long safePayTransSuccessSingleVeryCount = safePayOrderManager.statUserSingleVeryCount(userId,minEndTime, maxEndTime, SafePayOrderStatus.SUCCESS);
        //安全发单笔超过500金额失败笔数
        long safePayTransFailSingleVeryCount = safePayOrderManager.statUserSingleVeryCount(userId,minEndTime, maxEndTime,SafePayOrderStatus.FAIL);
        //安全发单笔超过10000金额成功笔数
        long safePayTransSuccessLargeCount = safePayOrderManager.statUserLargeCount(userId,minEndTime, maxEndTime, SafePayOrderStatus.SUCCESS);
        //安全发超过500万账户数
        long safePayTransVeryAlipayUserCount = safePayBatchManager.sumUserTotalVeryAlipayUserCount(userId,minEndTime, maxEndTime);
        //payTransBatch表统计
        PartnerUserPayTransDayStatModel companyPayTransDayStatModel = payTransBatchManager.sumPartnerUserPayTransDay(userId,minEndTime,maxEndTime);
        //safePayTransBatch表统计
        PartnerUserSafePayTransDayStatModel companySafePayTransDayStatModel = safePayBatchManager.sumPartnerUserSafePayTransDay(userId,minEndTime,maxEndTime);

        //设值
        //服务费充值金额
        stat.setServiceChargeFee(new BigDecimal(serviceChargeFee).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
        //批量有密单笔超过500金额成功笔数
        stat.setPayTransSuccessSingleVeryCount(payTransSuccessSingleVeryCount);
        //批量有密单笔超过500金额失败笔数
        stat.setPayTransFailSingleVeryCount(payTransFailSingleVeryCount );
        //批量有密单笔超过10000金额成功笔数
        stat.setPayTransSuccessLargeCount(payTransSuccessLargeCount);
        //批量有密超过500万账户数
        stat.setPayTransVeryAlipayUserCount(payTransVeryAlipayUserCount);
        //安全发单笔超过500金额成功笔数
        stat.setSafePayTransSuccessSingleVeryCount(safePayTransSuccessSingleVeryCount);
        //安全发单笔超过500金额失败笔数
        stat.setSafePayTransFailSingleVeryCount(safePayTransFailSingleVeryCount);
        //安全发单笔超过10000金额成功笔数
        stat.setSafePayTransSuccessLargeCount(safePayTransSuccessLargeCount);
        //安全发超过500万账户数
        stat.setSafePayTransVeryAlipayUserCount(safePayTransVeryAlipayUserCount);
        //payTransBatch表
        stat.setPayTransCount(companyPayTransDayStatModel.getPayTransCount());
        stat.setPayTransSuccessCount(companyPayTransDayStatModel.getPayTransSuccessCount());
        stat.setPayTransFailCount(companyPayTransDayStatModel.getPayTransFailCount());
        stat.setPayTransServicePrice(new BigDecimal(companyPayTransDayStatModel.getPayTransServicePrice()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
        stat.setPayTransAmount(companyPayTransDayStatModel.getPayTransAmount());
        stat.setPayTransSuccessAmount(companyPayTransDayStatModel.getPayTransSuccessAmount());
        stat.setPayTransFailAmount(companyPayTransDayStatModel.getPayTransFailAmount());
        stat.setTotalPayTransBenefit(new BigDecimal(companyPayTransDayStatModel.getTotalPayTransBenefit()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
        //safePayTransBatch
        stat.setSafePayTransCount(companySafePayTransDayStatModel.getSafePayTransCount());
        stat.setSafePayTransSuccessCount(companySafePayTransDayStatModel.getSafePayTransSuccessCount());
        stat.setSafePayTransFailCount(companySafePayTransDayStatModel.getSafePayTransFailCount());
        stat.setSafePayTransAmount(companySafePayTransDayStatModel.getSafePayTransAmount());
        stat.setSafePayTransSuccessAmount(companySafePayTransDayStatModel.getSafePayTransSuccessAmount());
        stat.setSafePayTransFailAmount(companySafePayTransDayStatModel.getSafePayTransFailAmount());
        stat.setSafePayTransServicePrice(new BigDecimal(companySafePayTransDayStatModel.getSafePayTransServicePrice()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
        stat.setTotalSafePayTransBenefit(new BigDecimal(companySafePayTransDayStatModel.getTotalSafePayTransBenefit()).multiply(new BigDecimal("0.01")).setScale(2, RoundingMode.HALF_UP));
        //总和数据入库
        stat.setTotalCount(stat.getPayTransCount() + stat.getSafePayTransCount());
        stat.setTotalSuccessCount(stat.getPayTransSuccessCount() + stat.getSafePayTransSuccessCount());
        stat.setTotalFailCount(stat.getPayTransFailCount() + stat.getSafePayTransFailCount());

        stat.setTotalServicePrice(stat.getPayTransServicePrice().add(stat.getSafePayTransServicePrice()));

        stat.setTotalTransAmount(stat.getPayTransAmount().add(stat.getSafePayTransAmount()));
        stat.setTotalSuccessTransAmount(stat.getPayTransSuccessAmount().add(stat.getSafePayTransSuccessAmount()));
        stat.setTotalFailTransAmount(stat.getPayTransFailAmount().add(stat.getSafePayTransFailAmount()));

        stat.setTotalBenefit(stat.getTotalPayTransBenefit().add(stat.getTotalSafePayTransBenefit()));
        stat.setTotalSuccessSingleVeryCount(stat.getPayTransSuccessSingleVeryCount() + stat.getSafePayTransSuccessSingleVeryCount());
        stat.setTotalFailSingleVeryCount(stat.getPayTransFailSingleVeryCount() + stat.getSafePayTransFailSingleVeryCount());

        //单笔超过10000金额成功笔数 总和数据
        stat.setTotalSuccessLargeCount(stat.getPayTransSuccessLargeCount() + stat.getSafePayTransSuccessLargeCount());
        //入库
        UserRealTimeStat beforeStat = userRealTimeStatManager.getByUserId(userId);
        if (beforeStat != null) {
            stat.setId(beforeStat.getId());
            userRealTimeStatManager.update(stat);
        } else {
            userRealTimeStatManager.save(stat);
        }

    }
}
